﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace Watson.TemporaryFilesDeleter
{
    /// <summary>
    /// Provides a method to filter a collection of files by the size of the
    /// file.
    /// </summary>
    public class FileSizeFileFilter : FileFilter
    {
        #region Private Fields

        /// <summary>
        /// The smallest value for the size of a file, in bytes, which will
        /// result in the file passing the filter and being included in the 
        /// output collection.
        /// </summary>
        private long minimumFileSize;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the smallest value for the size of a file, in bytes,
        /// which will result in the file passing the filter and being included
        /// in the output collection.
        /// </summary>
        public long MinimumFileSize
        {
            get
            {
                return this.minimumFileSize;
            }
            set
            {
                if (value < 0)
                {
                    throw GetMinimumFileSizeTooSmallException("value");
                }
                

                this.minimumFileSize = value;
            }
        }

        #endregion

        #region Protected Methods

        /// <summary>
        /// Determines whether to include a specific file from the input
        /// collection in the output collection.
        /// </summary>
        /// <param name="file">
        /// The file for which to determine its inclusion in the output
        /// collection.
        /// </param>
        /// <returns>
        /// System.Bool
        /// <para>
        /// True if the size of the file is equal to or greater than
        /// <see cref="MinimumFileSize"/> and thus should be included in
        /// the output collection; else, false.
        /// </para>
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="file"/> was null.
        /// </exception>
        protected override bool IncludeFile(System.IO.FileInfo file)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }


            if (file.Length >= this.MinimumFileSize)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region Private Static Methods

        /// <summary>
        /// Obtains an <see cref="System.ArgumentOutOfRangeException"/>
        /// suitable for throwing when an attempt is made to set the minimum
        /// file size to a value that is below the lowest acceptable value
        /// (0).
        /// </summary>
        /// <param name="paramName">
        /// The name of the parameter that contained the out of range value. It
        /// will be included in the returned exception.
        /// </param>
        /// <returns>
        /// System.ArgumentOutRangeException
        /// <para>
        /// An exception detailing the acceptable range of the minimum file
        /// size.
        /// </para>
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="paramName"/> was null.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="paramName"/> was a zero-length string or consisted
        /// entirely of whitespace.
        /// </exception>
        private static ArgumentOutOfRangeException
            GetMinimumFileSizeTooSmallException(string paramName)
        {
            if (paramName == null)
            {
                throw new ArgumentNullException("paramName");
            }
            else if (String.IsNullOrWhiteSpace(paramName))
            {
                throw new ArgumentException(
                    "Cannot be a zero-length string or consist entirely of"
                    + " whitespace.",
                    "paramName");
            }


            string message = "Minimum file size must exceed 0 bytes.";

            ArgumentOutOfRangeException argumentOutOfRangeException =
                new ArgumentOutOfRangeException(paramName, message);

            return argumentOutOfRangeException;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Obtains a string representation of the current FileSizeFileFilter.
        /// </summary>
        /// <returns>
        /// System.String
        /// <para>
        /// String representing the current FileSizeFileFilter.
        /// </para>
        /// </returns>
        public override string ToString()
        {
            string format = 
                "FileSizeFileFilter: {0:N0}";

            string value = 
                String.Format(CultureInfo.CurrentCulture,
                              format,
                              this.MinimumFileSize);

            return value;
        }

        #endregion

        #region Public Constructors

        /// <summary>
        /// Initialises a new instance of the FileSizeFileFilter class.
        /// </summary>
        public FileSizeFileFilter()
        { }

        /// <summary>
        /// Initialises a new instance of the FileSizeFileFilter class
        /// specifying a value for the minimum file size.
        /// </summary>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <param name="minimumFileSize"/> was less than zero.
        /// </exception>
        public FileSizeFileFilter(long minimumFileSize)
        {
            if (minimumFileSize < 0)
            {
                throw GetMinimumFileSizeTooSmallException("minimumFileSize");
            }


            this.MinimumFileSize = minimumFileSize;
        }

        #endregion
    }
}
